package com.lenovo.agent.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lenovo.agent.config.GitLabConfig;
import com.lenovo.agent.model.gitlab.MergeRequestComment;
import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Slf4j
@Service
public class CodeReviewService {

    @Autowired
    private GitLabConfig gitLabConfig;

    @Autowired
    private AIReviewService aiReviewService;

    private final ObjectMapper objectMapper = new ObjectMapper();
    private final RestTemplate restTemplate = new RestTemplate();

    public void processMergeRequest(String payload) {
        try {
            JsonNode root = objectMapper.readTree(payload);
            String action = root.get("object_attributes").get("action").asText();

            if ("open".equals(action) || "update".equals(action)) {
                String projectId = root.get("project").get("id").asText();
                String mergeRequestIid = root.get("object_attributes").get("iid").asText();

                List<CodeChange> changes = getChanges(projectId, mergeRequestIid);
                for (CodeChange change : changes) {
                    String aiReview = "写的不错";
//                    String aiReview = aiReviewService.performCodeReview(change.getContent());
                    addReviewComment(projectId, mergeRequestIid, change, aiReview);
                }
            }
        } catch (Exception e) {
            log.error("处理 MR 失败", e);
        }
    }

    @Data
    @Builder
    private static class CodeChange {
        private String path;
        private String content;
        private List<ChangedLine> changedLines;
    }

    @Data
    @Builder
    private static class ChangedLine {
        private String type; // "new" or "old"
        private int lineNumber;
        private String content;
        private String lineCode;
    }

    private List<CodeChange> getChanges(String projectId, String mergeRequestIid) {
        try {
            String url = String.format("%s/api/v4/projects/%s/merge_requests/%s/changes",
                    gitLabConfig.getUrl(), projectId, mergeRequestIid);

            HttpHeaders headers = new HttpHeaders();
            headers.set("PRIVATE-TOKEN", gitLabConfig.getToken());

            ResponseEntity<JsonNode> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    new HttpEntity<>(headers),
                    JsonNode.class
            );

            List<CodeChange> changes = new ArrayList<>();
            if (response.getBody() != null) {
                JsonNode changes_node = response.getBody().get("changes");
                for (JsonNode change : changes_node) {
                    String path = change.get("new_path").asText();
                    List<ChangedLine> changedLines = new ArrayList<>();

                    // 解析差异信息
                    String diff = change.get("diff").asText();
                    String[] lines = diff.split("\n");
                    int newLineNumber = 0;
                    int oldLineNumber = 0;

                    for (String line : lines) {
                        if (line.startsWith("+") && !line.startsWith("+++")) {
                            newLineNumber++;
                            changedLines.add(ChangedLine.builder()
                                    .type("new")
                                    .lineNumber(newLineNumber)
                                    .content(line.substring(1))
                                    .build());
                        } else if (line.startsWith("-") && !line.startsWith("---")) {
                            oldLineNumber++;
                            changedLines.add(ChangedLine.builder()
                                    .type("old")
                                    .lineNumber(oldLineNumber)
                                    .content(line.substring(1))
                                    .build());
                        } else if (!line.startsWith("\\") && !line.startsWith("+++") && !line.startsWith("---")) {
                            newLineNumber++;
                            oldLineNumber++;
                        }
                    }

                    changes.add(CodeChange.builder()
                            .path(path)
                            .content(diff)
                            .changedLines(changedLines)
                            .build());
                }
            }

            return changes;
        } catch (Exception e) {
            log.error("获取 MR 变更失败", e);
            return Collections.emptyList();
        }
    }

    private void addReviewComment(String projectId, String mergeRequestIid,
                                  CodeChange change, String aiReview) {
        try {
            String url = String.format("%s/api/v4/projects/%s/merge_requests/%s/discussions",
                    gitLabConfig.getUrl(), projectId, mergeRequestIid);

            // 首先获取 MR 的详细信息以获取必要的 SHA
            String mrUrl = String.format("%s/api/v4/projects/%s/merge_requests/%s",
                    gitLabConfig.getUrl(), projectId, mergeRequestIid);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("PRIVATE-TOKEN", gitLabConfig.getToken());

            ResponseEntity<JsonNode> mrResponse = restTemplate.exchange(
                    mrUrl,
                    HttpMethod.GET,
                    new HttpEntity<>(headers),
                    JsonNode.class
            );

            if (mrResponse.getBody() == null) {
                throw new RuntimeException("无法获取 MR 信息");
            }

            String baseSha = mrResponse.getBody().get("diff_refs").get("base_sha").asText();
            String startSha = mrResponse.getBody().get("diff_refs").get("start_sha").asText();
            String headSha = mrResponse.getBody().get("diff_refs").get("head_sha").asText();

            // 为每个修改的行添加评论
            for (ChangedLine line : change.getChangedLines()) {
                if ("new".equals(line.getType())) {  // 只对新增的行添加评论
                    // 生成 line_code
                    String lineCode = "AAAA";

                    MergeRequestComment comment = MergeRequestComment.builder()
                            .body(aiReview)
                            .lineCode(lineCode)
                            .position(MergeRequestComment.Position.builder()
                                    .baseSha(baseSha)
                                    .startSha(startSha)
                                    .headSha(headSha)
                                    .positionType("text")
                                    .newPath(change.getPath())
                                    .newLine(line.getLineNumber())
                                    .oldPath(change.getPath())
                                    .oldLine(null)
                                    .build())
                            .build();

                    HttpEntity<MergeRequestComment> requestEntity =
                            new HttpEntity<>(comment, headers);

                    ResponseEntity<JsonNode> response = restTemplate.exchange(
                            url,
                            HttpMethod.POST,
                            requestEntity,
                            JsonNode.class
                    );

                    if (!response.getStatusCode().is2xxSuccessful()) {
                        log.error("添加评论失败: {}", response.getBody());
                    }
                }
            }
        } catch (Exception e) {
            log.error("添加评论失败", e);
        }
    }

    private String generateLineCode(String commitId, String filePath, int lineNumber) {
        // GitLab 的 line_code 格式通常是: {commit_id}_{file_path}_{line_number}
        String normalizedPath = filePath.replace('/', '_');
        return String.format("%s_%s_%d", commitId, normalizedPath, lineNumber);
    }
}